<?php
/**
 *RefundServices
 * @author tan bing
 * @date 2021-11-16 11:55
 */


namespace Modules\Order\Services\Common;


use EasyWeChat\Factory;
use EasyWeChat\Kernel\Exceptions\InvalidConfigException;
use EasyWeChat\MiniProgram\Application;
use Illuminate\Support\Facades\Auth;
use Modules\Order\Entities\Goods;
use Modules\Order\Entities\OrderDetail;
use Modules\Order\Entities\User;
use Modules\Order\Entities\UserCapitalLog;
use Modules\Order\Services\Api\BaseService;
use Modules\Wechatapplet\Entities\WechatAppletSetting;

class RefundServices extends BaseService
{

    /**
     * @var Application
     * @author tan bing
     */
    private $app;

    /**
     * @var array
     * @author tan bing
     */
    private array $config;

    /**
     * RefundServices constructor.
     * @throws \Exception
     * @author tan bing
     * @date 2021-11-16 11:57
     */
    public function __construct()
    {
        $baseConfig = WechatAppletSetting::query()->where('group', 'base')->get();
        foreach ($baseConfig as $item) {
            $item->code == 'app_id' && $appId = $item->value;
            $item->code == 'app_secret' && $appSecret = $item->value;
            $item->code == 'mch_id' && $mchId = $item->value;
            $item->code == 'mch_key' && $mchKey = $item->value;
            $item->code == 'cert_pem' && $certPem = $item->value;
            $item->code == 'key_pem' && $keyPem = $item->value;
        }
        $this->config = [
            'app_id'     => $appId ?? '',
            'secret' => $appSecret ?? '',
            'mch_id'     => $mchId ?? '',
            'key'    => $mchKey ?? '',
            'cert_pem'   => $certPem ?? '',
            'key_pem'    => $keyPem ?? '',
            'cert_path'      => base_path('cacert/apiclient_cert.pem'),
            'key_path'       => base_path('cacert/apiclient_key.pem'),
        ];
        try {
            $this->app = Factory::payment($this->config);
        } catch (\Exception $e) {
            throw new \Exception($e->getMessage());
        }
    }

    /**
     * @param $order
     * @param $refundNo
     * @param $refundFee
     * @param $payId
     * @return bool
     * @throws \Exception
     * @author tan bing
     * @date 2021-11-16 17:40
     */
    public function refundHandle($order, $refundNo, $refundFee, $payId)
    {
        if($payId == 0) {
            $this->wxRefund($order, $refundNo, $refundFee);
        } elseif($payId == 1) {
            // 余额退款
            $this->balanceRefund($order, $refundFee);
        }

        return true;
    }

    /**
     * 微信退款
     * @param $order
     * @param $refundNo
     * @param $refundFee
     * @param null $refundAccount
     * @return bool
     * @throws \Exception
     * @author tan bing
     * @date 2021-11-16 17:16
     */
    public function wxRefund($order, $refundNo, $refundFee, $refundAccount = null)
    {
        try {
            $result = $this->app->refund->byOutTradeNumber($order->order_no, $refundNo, $refundFee * 100, $refundFee * 100, [
                'refund_desc' => '订单取消 --退款',
            ]);
            if(!$result)
                throw new \Exception('订单取消失败，退款失败，服务端配置出错');

            if ($result['return_code'] != 'SUCCESS')
                throw new \Exception('订单取消失败，退款失败，' . $result['return_msg']);

            if (isset($res['err_code']) && $result['err_code'] == 'NOTENOUGH' && !$refundAccount) {
                // 交易未结算资金不足，请使用可用余额退款
//                return $this->wxRefund($order, $refundFee, 'REFUND_SOURCE_RECHARGE_FUNDS');
                throw new \Exception('订单取消失败，退款失败，易未结算资金不足');
            }
            if ($result['result_code'] != 'SUCCESS')
                throw new \Exception('订单取消失败，退款失败，' . $result['err_code_des']);

        } catch (InvalidConfigException $e) {
            throw new \Exception($e->getMessage());

        } catch (\Exception $e) {
            throw new \Exception($e->getMessage());
        }

        return true;
    }

    /**
     * 退款到余额
     * @param $order
     * @param $refundFee
     * @throws \Exception
     * @author tan bing
     * @date 2021-11-16 17:20
     */
    public function balanceRefund($order, $refundFee)
    {
        $user = User::find($order->user_id);
        $user->money += floatval($refundFee);
        $data['user_id'] = $user->id;
        $data['operate'] = 3;   //退回
        $data['type'] = 1;      //余额
        $data['admin_id'] = Auth::guard('admin')->id();
        $data['operate_name'] = Auth::guard('admin')->user()->nickname;
        $data['amount'] = $order->pay_price;
        $data['description'] = '商城订单退款,订单号【' . $order->order_no . '】';
        UserCapitalLog::saveLog($data);

        if(!$user->save())
            throw new \Exception('退款失败');
    }

    /**
     * 商品库存恢复
     * @param $order
     * @return bool
     * @author tan bing
     * @date 2021-11-16 17:23
     */
    public function goodsStockAdNum($order)
    {
        $order_detail_list = OrderDetail::query()->where([['order_id', '=', $order->id], ['is_delete', '=', 0]])->get();
        //库存恢复
        foreach ($order_detail_list as $order_detail) {
            $goods        = Goods::find($order_detail->goods_id);
            $attr_id_list = [];
            foreach (json_decode($order_detail->goods_attr) as $item) {
                array_push($attr_id_list, $item->attr_id);
            }
            $goods->numAdd($attr_id_list, $order_detail->goods_num, $goods);
        }

        return true;
    }
}